///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#ifndef __SceneManagerEnumerator_H__
#define __SceneManagerEnumerator_H__

#include "OgrePrerequisites.h"

#include "OgreSceneManager.h"
#include "OgreSingleton.h"
#include "OgreIteratorWrappers.h"

namespace Ogre {
    
	
	
	/// Factory for default scene manager
	class _OgreExport DefaultSceneManagerFactory : public SceneManagerFactory
	{
	protected:
		void initMetaData(void) const;
	public:
		DefaultSceneManagerFactory() {}
		~DefaultSceneManagerFactory() {}
		/// Factory type name
		static const String FACTORY_TYPE_NAME;
		SceneManager* createInstance(const String& instanceName);
		void destroyInstance(SceneManager* instance);
	};
	/// Default scene manager
	class _OgreExport DefaultSceneManager : public SceneManager
	{
	public:
		DefaultSceneManager(const String& name);
		~DefaultSceneManager();
		const String& getTypeName(void) const;
	};

    
    class _OgreExport SceneManagerEnumerator : public Singleton<SceneManagerEnumerator>, public MemAlloc_SceneCtrl
    {
	public:
		/// Scene manager instances, indexed by instance name
		typedef map<String, SceneManager*>::type Instances;
		/// List of available scene manager types as meta data
		typedef vector<const SceneManagerMetaData*>::type MetaDataList;
    private:
		/// Scene manager factories
		typedef list<SceneManagerFactory*>::type Factories;
		Factories mFactories;
		Instances mInstances;
		/// Stored separately to allow iteration
		MetaDataList mMetaDataList;
		/// Factory for default scene manager
		DefaultSceneManagerFactory mDefaultFactory;
		/// Count of creations for auto-naming
		unsigned long mInstanceCreateCount;
		/// Currently assigned render system
		RenderSystem* mCurrentRenderSystem;


    public:
        SceneManagerEnumerator();
        ~SceneManagerEnumerator();

		
		void addFactory(SceneManagerFactory* fact);

		
		void removeFactory(SceneManagerFactory* fact);

		
		const SceneManagerMetaData* getMetaData(const String& typeName) const;

		typedef ConstVectorIterator<MetaDataList> MetaDataIterator;
		
		MetaDataIterator getMetaDataIterator(void) const;

		
		SceneManager* createSceneManager(const String& typeName, 
			const String& instanceName = StringUtil::BLANK);

		
		SceneManager* createSceneManager(SceneTypeMask typeMask, 
			const String& instanceName = StringUtil::BLANK);

		
		void destroySceneManager(SceneManager* sm);

		
		SceneManager* getSceneManager(const String& instanceName) const;

		
		bool hasSceneManager(const String& instanceName) const;

		typedef MapIterator<Instances> SceneManagerIterator;
		
		SceneManagerIterator getSceneManagerIterator(void);

        
        void setRenderSystem(RenderSystem* rs);

        /// Utility method to control shutdown of the managers
        void shutdownAll(void);
        
        static SceneManagerEnumerator& getSingleton(void);
        
        static SceneManagerEnumerator* getSingletonPtr(void);

    };

	
	

}

#endif
